#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>

#define BUFSIZE 1024

using namespace std;

enum errornum
{
    SOCK_FAILED = 1,
    BIND_FAILED,
    LISTEN_FAILED,
    ACCEPT_FAILED,
    CONNECT_FAILED
};

class tcpclient
{
public:
    // 构造
    tcpclient(const string &serverip, uint16_t serverport)
        : _sock(-1), _serverip(serverip), _serverport(serverport)
    {
        // 1、创建套接字
        _sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_sock == -1) // 套接字创建失败
        {
            cerr << "套接字创建失败" << endl;
            exit(SOCK_FAILED);
        }

        cout << "创建套接字成功，sock:" << _sock << endl;

        // 2、建立链接
        // 2.1构建服务端属性结构·
        struct sockaddr_in serverinfor;
        bzero(&serverinfor, sizeof(serverinfor));
        serverinfor.sin_family = AF_INET;
        serverinfor.sin_port = htons(_serverport);
        serverinfor.sin_addr.s_addr = inet_addr(_serverip.c_str());

        //.2.构建链接
        int n = connect(_sock, (struct sockaddr *)&serverinfor, sizeof(serverinfor));
        cout << n << endl;

        if (n != 0)
        {
            // cerr << "建立连接失败" << endl;
            perror("建立连接失败");
            exit(CONNECT_FAILED);
        }

        cout << "建立连接成功" << endl;
    }

    // 删除拷贝构造
    tcpclient(const tcpclient &) = delete;

    // 删除赋值重做
    tcpclient &operator=(const tcpclient &) = delete;

    // 析构
    ~tcpclient()
    {
        close(_sock); // 关闭文件
    }

    // 开始通信
    void start()
    {
        string message;
        while (true)
        {
            // 1、从键盘读取数据
            cout << "请输入# ";
            fflush(stdout);
            getline(cin, message);

            // 2、将读取到的数据发送给服务端
            write(_sock, message.c_str(), message.size());

            // 3、接收服务器发送的反馈信息
            char buffer[BUFSIZE];
            int n = read(_sock, buffer, sizeof(buffer) - 1);
            if (n >= 0)
                buffer[n] = 0;

            cout << "服务端回复# " << buffer << endl;
        }
    }

private:
    int _sock;
    string _serverip;
    uint16_t _serverport;
};